
#ifndef SOURCEEDIT_H
#define SOURCEEDIT_H

#include <BSet>
#include <BTree>
#include <BWidget>
#include <BImage>
#include <BSlider>
#include <BTextEdit>
#include <BRectArray>
#include <BPainter>
#include <BEntry>
#include <BSource>

#include "SourceFormat.h"
#include "PromptBox.h"

struct ScriptInfo : public BThing
{
	ScriptInfo()
	{
		changed = true;
		buildCount = 0;
	}
	BString				fileName;
	bool				changed;
	int					buildCount;
};

struct SourceInfo : public BThing
{
	SourceInfo()
	{
		compilable = false;
	}
	bool				compilable;
	BEntryHolder		entry;
	BStringArray		depends;
	BExpHolderArray		exps;;
};
typedef BArray<SourceInfo*>	SourceInfoArray;

class SourceEdit : public BTextEdit
{
	struct Chunk
	{
		Chunk()
		{
			visible = true;
			begin = -1;
			end = -1;
		}
		bool operator == (const BExp* exp) const
		{
			return this->exp == exp;
		}

		bool		visible;
		int			begin;
		int			end;
		BRect		rect;
		BRect		head;
		BRect		tail;
		BExpHolder	exp;
	};
	typedef BTree<Chunk>	ChunkTree;
public:
	SourceEdit(BWidget* parent = 0);
	~SourceEdit();

protected:
	void analyseSource();

	void freshFormat(const BExpHolderArray& document);
	void drawErrorFlag(BPainter& painter, SourceFormat::Item* item);

	void createChunk(BExp* exp, ChunkTree::iterator it);
	void freshChunk(ChunkTree::iterator& it);
	void foldedChunk(ChunkTree::iterator& it);
	ChunkTree::iterator chunkUnder(const BPoint& point);
	ChunkTree::iterator chunkUnder(ChunkTree::iterator& it, const BPoint& point);
	ChunkTree::iterator chunkOfLine(int line);
	ChunkTree::iterator chunkOfLine(ChunkTree::iterator& it, int line);
	void drawChunk(BPainter& painter, ChunkTree::iterator& it);

protected:
	void slotAssetChanged(BObject* object, const BValue& value);
	void slotTextChanged(BObject* object, const BValue& value);
	void slotTextEdited(BObject* object, const BValue& value);
	void slotFlushed(BObject* object, const BValue& value);
	void slotScriptMessage(BObject* object, const BValue& value);

protected:
	virtual void updateEvent(const BEvent& event);

	virtual void showEvent(const BEvent& event);
	virtual void closeEvent(const BEvent& event);

	virtual void resizeEvent(const BEvent& event);

	virtual void keyUpEvent(const BKeyEvent& keyEvent);

	virtual void styleEvent(const BEvent& event);
	virtual void freshEvent(const BEvent& event);
	virtual void paintEvent(const BEvent& event);

	virtual void mousePressEvent(const BMouseEvent& mouseEvent);
	virtual void mouseReleaseEvent(const BMouseEvent& mouseEvent);
	virtual void mouseMoveEvent(const BMouseEvent& mouseEvent);

private:
	BRect					_breakArea;
	BSet<int>				_breakLines;
	BRect					_chunkArea;
	BTree<Chunk>			_chunkTree;
	BMap<BString, BString>	_messagMap;
	ChunkTree::iterator		_hoveredChunk;
	BValue					_codeRectsValue;
	BHolder<PromptBox>		_promptBox;
	double					_hoverTime;
	BHolder<const BImage>	_minusImage;
	BHolder<const BImage>	_plusImage;
};

#endif